package com.xhwl.logistics.service.impl.http;


import cn.hutool.http.HttpException;
import cn.hutool.http.HttpRequest;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xhwl.common.exception.ApplicationException;
import com.xhwl.common.exception.BusinessException;
import com.xhwl.common.vo.cent.vehicle.CarVO;
import com.xhwl.logistics.constant.HongMenConstant;
import com.xhwl.logistics.util.AboutDateUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 对接红门厂商的Http请求
 */
@Slf4j
//@Service
public class HongMenHttpServiceImpl {

    //访客车允许通行次数
    private static final Integer authTimes = 99;
    //访客车权限注销方式
    private static final Integer deAuthWay = 1;
    //通行证类型
    private static final String passTypeName = "固定车";
    //起杆原因
    private static final String openReason = "开闸";
    //落杆原因
    private static final String closeReason = "关闸";
    //是否为落杆
    private static final String isDown = "1";
    //分页查询的页数大小
    private static final Integer pageSize = 500;

    /**
     * 红门返回结果判断
     * @param resultObj
     */
    private void hongMenResponseHandler(JSONObject resultObj){
        String resultCode = resultObj.getString("result_code");
        String code = resultObj.getString("code");
        if(!StringUtils.equals(resultCode, "0") && !StringUtils.equals(code, "0")){
            throw new BusinessException(resultObj.getString("message"));
        }
    }

    /**
     * 获取全部区域的剩余车位
     */
    public JSONObject getAllAreaCarSpot(String path){
        Map<String, Object> params = new HashMap<>();
        params.put("do", HongMenConstant.QUERY_AREA_INFO_DO);
        JSONObject resultObj = this.post(path + HongMenConstant.QUERY_AREA_INFO, params);
        this.hongMenResponseHandler(resultObj);
        return JSONObject.parseObject(resultObj.getString("data"));
    }

    /**
     * 访客车授权
     */
    public void addVisitorCar(String path, CarVO carVO){
        Map<String, Object> params = new HashMap<>();
        params.put("do", HongMenConstant.ADD_VISITOR_CAR_DO);
        params.put("car_plate_no", carVO.getPlateNumber());
        params.put("auth_times", authTimes);
        params.put("allow_enter_time_begin", AboutDateUtil.dateToString(carVO.getValidBeginTime()));
        params.put("allow_enter_time_end", AboutDateUtil.dateToString(carVO.getValidEndTime()));
        JSONObject resultObj = this.post(path + HongMenConstant.ADD_VISITOR_CAR, params);
        this.hongMenResponseHandler(resultObj);
    }

    /**
     * 访客车授权注销
     */
    public void deleteVisitorCar(String path, String plateNumber){
        Map<String, Object> params = new HashMap<>();
        params.put("do", HongMenConstant.DELETE_VISITOR_CAR_DO);
        params.put("car_plate_no", plateNumber);
        params.put("de_auth_way", deAuthWay);
        JSONObject resultObj = this.post(path + HongMenConstant.DELETE_VISITOR_CAR, params);
        this.hongMenResponseHandler(resultObj);
    }

    /**
     * 注册车牌通行证
     */
    public void addCar(String path, String plateNumber){
        Map<String, Object> params = new HashMap<>();
        params.put("do", HongMenConstant.ADD_CAR_DO);
        params.put("register_plate", plateNumber);
        params.put("pass_type_name", passTypeName);
        JSONObject resultObj = this.post(path + HongMenConstant.ADD_CAR, params);
        this.hongMenResponseHandler(resultObj);
    }

    /**
     * 更改月卡通行证的有效时间
     */
    public JSONObject editCarTime(String path, String plateNumber, Date endTime){
        Map<String, Object> params = new HashMap<>();
        params.put("do", HongMenConstant.EDIT_CAR_TIME_DO);
        params.put("car_plate_no", plateNumber);
        params.put("deadline", AboutDateUtil.dateToString(endTime, "yyyy-MM-dd"));
        JSONObject resultObj = this.post(path+ HongMenConstant.EDIT_CAR_TIME, params);
        this.hongMenResponseHandler(resultObj);
        return JSONObject.parseObject(resultObj.getString("data"));
    }

    /**
     * 通行证（车牌）注销
     */
    public void deleteCar(String path, String plateNumber){
        Map<String, Object> params = new HashMap<>();
        params.put("do", HongMenConstant.DELETE_CAR_DO);
        params.put("car_plate_no", plateNumber);
        JSONObject resultObj = this.post(path + HongMenConstant.DELETE_CAR, params);
        this.hongMenResponseHandler(resultObj);
    }

    /**
     * 远程起杆
     */
    public void openChannel(String path, String channelId){
        Map<String, Object> params = new HashMap<>();
        Map<String, Object> jsonParams = new HashMap<>();
        params.put("do", HongMenConstant.CONTROL_CHANNEL_OPEN_DO);
        jsonParams.put("channelId", channelId);
        jsonParams.put("reason", openReason);
        JSONObject resultObj = this.postJSONParam(path + HongMenConstant.CONTROL_CHANNEL_OPEN, params, jsonParams);
        this.hongMenResponseHandler(resultObj);
    }

    /**
     * 远程落杆
     */
    public void closeChannel(String path, String channelId){
        Map<String, Object> params = new HashMap<>();
        Map<String, Object> jsonParams = new HashMap<>();
        params.put("do", HongMenConstant.CONTROL_CHANNEL_CLOSE_DO);
        jsonParams.put("channelId", channelId);
        jsonParams.put("reason", closeReason);
        jsonParams.put("is_down", isDown);
        JSONObject resultObj = this.postJSONParam(path + HongMenConstant.CONTROL_CHANNEL_CLOSE, params, jsonParams);
        this.hongMenResponseHandler(resultObj);
    }

    /**
     * 获取通道信息
     */
    public JSONArray queryPassageInfo(String path){
        Map<String, Object> params = new HashMap<>();
        params.put("do", HongMenConstant.QUERY_PASSAGE_INFO_DO);
        JSONObject resultObj = this.post(path + HongMenConstant.QUERY_PASSAGE_INFO, params);
        this.hongMenResponseHandler(resultObj);
        return JSONObject.parseArray(resultObj.getString("channels"));
    }

    /**
     * 获取通道对应的设备信息
     */
    public JSONArray queryDeviceByPassage(String path, String channelId){
        Map<String, Object> params = new HashMap<>();
        Map<String, Object> jsonParams = new HashMap<>();
        JSONObject resultObj = new JSONObject();
        params.put("do", HongMenConstant.QUERY_DEVICE_INFO_DO);
        if(channelId != null){
            jsonParams.put("channel_id", channelId);
            resultObj = this.postJSONParam(path + HongMenConstant.QUERY_DEVICE_INFO, params, jsonParams);
        }else{
            resultObj = this.post(path + HongMenConstant.QUERY_DEVICE_INFO, params);
        }
        this.hongMenResponseHandler(resultObj);
        return JSONObject.parseArray(resultObj.getString("equipment"));
    }

    /**
     * 通过车牌号查询车辆
     */
    public JSONArray queryCarByPlateNumber(String path, String plateNumber){
        Map<String, Object> params = new HashMap<>();
        params.put("do", HongMenConstant.QUERY_CAR_DO);
        params.put("car_plate_no", plateNumber);
        JSONObject resultObj = this.post(path + HongMenConstant.QUERY_CAR, params);
        return JSONObject.parseArray(resultObj.getString("data"));
    }

    /**
     * 查询所有的通行证车辆
     */
    public JSONArray queryAllCar(String path){
        JSONArray carArr = new JSONArray();
        Integer pageNum = 1;
        JSONArray carPageArr = null;
        do {
            carPageArr = this.queryCar(path, pageNum);
            if(carPageArr.size() == 0){
                break;
            }
            carArr.addAll(carPageArr);
            ++pageNum;
        }while (carPageArr.size() == pageSize);
        return carArr;
    }

    /**
     * 分页查询通行证车辆
     */
    private JSONArray queryCar(String path, Integer pageNum){
        Map<String, Object> params = new HashMap<>();
        params.put("do", HongMenConstant.QUERY_CAR_DO);
        params.put("page_size", pageSize);
        params.put("page_num", pageNum);
        JSONObject resultObj = this.post(path + HongMenConstant.QUERY_CAR, params);
        this.hongMenResponseHandler(resultObj);
        return JSONObject.parseArray(resultObj.getString("data"));
    }

    /**
     * 查询车位信息
     */
    public JSONObject queryParkingLot(String path){
        Map<String, Object> params = new HashMap<>();
        params.put("do", HongMenConstant.QUERY_PARKING_LOT_INFO_DO);
        JSONObject resultObj = this.post(path + HongMenConstant.QUERY_PARKING_LOT_INFO, params);
        this.hongMenResponseHandler(resultObj);
        return JSONObject.parseObject(resultObj.getString("data"));
    }

    /**
     * post方式请求红门下行接口
     * @param path
     * @param params
     * @return
     */
    private JSONObject post(String path, Map<String, Object> params){
        String url = this.urlAndParanms(path, params);
        log.info("请求红门地址和参数为{}", url);
        String result = null;
        try {
            result = HttpRequest.post(url)
                    .execute()
                    .body();
        } catch (HttpException e) {
            log.error("请求红门接口网络异常：返回结果为{}", result);
            throw new ApplicationException("请求红门网络异常");
        }
        if(result.isEmpty()){
            log.error("请求红门接口返回值为空!");
            throw new ApplicationException();
        }
        log.info("请求红门接口的返回值为：{}",result);
        return JSONObject.parseObject(result);
    }

    /**
     * post方式请求红门下行接口,存在json数据
     * @param path
     * @param params
     * @return
     */
    private JSONObject postJSONParam(String path, Map<String, Object> params, Map<String, Object> jsonParams){
        String url = this.urlAndParanms(path, params);
        log.info("请求红门地址和参数为{}", url);
        String result = null;
        try {
            result = HttpRequest.post(url)
                    .body(JSONObject.toJSONString(jsonParams))
                    .execute()
                    .body();
        } catch (HttpException e) {
            log.error("请求红门接口网络异常：返回结果为{}", result);
            throw new ApplicationException("请求红门网络异常");
        }
        if(result.isEmpty()){
            log.error("请求红门接口返回值为空!");
            throw new ApplicationException();
        }
        log.info("请求红门接口的返回值为：{}",result);
        return JSONObject.parseObject(result);
    }


    /**
     * 将url与params进行组装
     */
    private String urlAndParanms(String url, Map<String,Object> params){
        if(params.isEmpty()){
            return url;
        }else{
            StringBuilder urlAndParams = new StringBuilder();
            urlAndParams.append(url+"?");
            params.forEach((k,v)->{
                urlAndParams.append(k).append("=").append(v).append("&");
            });
            String urlAndParamsStr = urlAndParams.toString();
            return urlAndParamsStr.substring(0,urlAndParamsStr.length()-1);
        }
    }
}
